
////////////////////////////////////////////////////////////
//	File:		"AL_ThreadPoolManager.cpp"
//	Author:		[AL] Anthony Lundquist
//	Created:	[AL] March 14, 2010
//	Purpose:	Manages all of the thread pools
//				- Singleton
////////////////////////////////////////////////////////////

#include "AL_ThreadPoolManager.h"
#include "AL_Task.h"
#include "TaskThread.h"

/* Data Members */

AL_ThreadPoolManager AL_ThreadPoolManager::sm_Instance;

/* Constructors */

AL_ThreadPoolManager::AL_ThreadPoolManager()
{

}

/* Accessors */

/* Mutators */

/* Other Functions */

void AL_ThreadPoolManager::Init()
{
}

void AL_ThreadPoolManager::Shutdown()
{
	for(unsigned int i=0 ; i<m_vRunningThreads.size(); i++)
	{
		m_vRunningThreads[i]->End();
		delete m_vRunningThreads[i];
	}
}

void AL_ThreadPoolManager::CreateThreadPool(int _nTryMaxThreads, bool _bRunAsSerial)
{
	m_vRunningThreads.resize(_nTryMaxThreads);

	for(unsigned int i=0 ; i < m_vRunningThreads.size() ; i++)
	{
		m_vRunningThreads[i] = new TaskThread();
		m_vRunningThreads[i]->Begin(true);
	}

	m_nNumDormentThreads = static_cast<int>(m_vRunningThreads.size());
}

void AL_ThreadPoolManager::SendTask(AL_Task* _pTask)
{
	m_vTaskPool.push_back(_pTask);
}

void AL_ThreadPoolManager::UpdatePool(float _fDelta)
{
	std::list<AL_Task*>::iterator iter;

	// if the task just finish notify the dependencies
	for(unsigned int i=0 ; i<m_vRunningThreads.size() ; i++)
	{
		if(m_vRunningThreads[i]->IsPaused())
		{
			if(m_vRunningThreads[i]->GetJustFinished())
			{
				m_vRunningThreads[i]->FinishTask();
				m_nNumDormentThreads++;
			}
		}
	}

	TaskThread* DormentThread = NULL;
	AL_Task* curTask = NULL;
	// process the thread pool
	if(m_nNumDormentThreads!=0)
	{
		for(iter = m_vTaskPool.begin(); iter != m_vTaskPool.end();)
		{
			curTask = (*iter);

			if(curTask->CheckIfCanRun())
			{
				for(unsigned int i=0 ; i<m_vRunningThreads.size() ; i++)
				{
					// if we find a dorment thread save it, otherwise check to see if one of the running threads is a dependency
					if(m_vRunningThreads[i]->IsPaused())
						DormentThread = m_vRunningThreads[i];
					else
						curTask->TryAddDependency(m_vRunningThreads[i]->GetTask(),m_vRunningThreads[i]->GetTask()->GetTaskType());
				}
			}
			// if we found a Dorment Thread and it can still run then we run the task
			if(curTask && DormentThread && curTask->CheckIfCanRun())
			{
				DormentThread->SetTask(curTask);
				DormentThread->Resume();
				m_nNumDormentThreads--;
				iter = m_vTaskPool.erase(iter);
				if(iter == m_vTaskPool.end())
					break;

				// reset the dorment thread
				DormentThread = NULL;
			}
			else
				iter++;
		}
	}
}

AL_ThreadPoolManager* AL_ThreadPoolManager::GetInstance()
{
	return &sm_Instance;
}

/* Destructor */

AL_ThreadPoolManager::~AL_ThreadPoolManager()
{

}

/* Protected Functions */

/* Private Functions */

